package adc.app.ui.wicket.security;

import java.io.Serializable;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.SimpleFormComponentLabel;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import adc.app.spec.IAutheBs;
import adc.app.spec.IUser;
import adc.app.spec.InvalidCredentialException;
import adc.app.ui.wicket.AlertFeedbackPanel;
import adc.app.ui.wicket.IMsgs;

public class LoginPanel extends Panel {
	
	private static final long serialVersionUID = 1L;

	private static final Logger LOG = LoggerFactory.getLogger(LoginPanel.class);
	
	private static final String ID_LOGIN_FORM = "loginForm";
	private static final String ID_USERNAME_LABEL = "usernameLabel";
	private static final String ID_USERNAME_FIELD = "username";
	private static final String ID_PASSWORD_LABEL = "passwordLabel";
	private static final String ID_PASSWORD_FIELD = "password";
	private static final String ID_SUBMIT_LOGIN_BTN = "submitLogin";
	private static final String ID_SUBMIT_LOGIN_LBL = "caption";
	private static final String ID_LOGIN_FORM_FEEDBACK = "loginFeedback";
	
	public static interface ILoginCallback extends Serializable {
		void onLogin(AjaxRequestTarget target, IUser user);
	}
	
	@SpringBean 
	private IAutheBs<IUser> authBS;
	private ILoginCallback callback;
	
	public LoginPanel(String id) {
		super(id);
		FormComponent<?> usernameField, passwordField;
		Form<Credentials> form = new Form<Credentials>(ID_LOGIN_FORM, new CompoundPropertyModel<Credentials>(new Credentials()));
		add(form.add(usernameField = new TextField<String>(ID_USERNAME_FIELD).setLabel(new ResourceModel(IMsgs.USERNAME)))
			.add(new SimpleFormComponentLabel(ID_USERNAME_LABEL, usernameField))
			.add(passwordField = new PasswordTextField(ID_PASSWORD_FIELD).setLabel(new ResourceModel(IMsgs.PASSWORD)))
			.add(new SimpleFormComponentLabel(ID_PASSWORD_LABEL, passwordField)))
		.add(new AlertFeedbackPanel(ID_LOGIN_FORM_FEEDBACK).setOutputMarkupId(true));
		
		usernameField.setRequired(true);
		form.add(new LoginSubmitLink(ID_SUBMIT_LOGIN_BTN)
			.add(new Label(ID_SUBMIT_LOGIN_LBL, new ResourceModel(IMsgs.LOGIN))));
	}

	protected final IAutheBs<IUser> getService() {
		return authBS;
	}
	
	public final LoginPanel setCallback(ILoginCallback callback) {
		this.callback = callback;
		return this;
	}

	protected static final class Credentials implements Serializable {
		private static final long serialVersionUID = 1L;
		private String username, password;
		public String getUsername() { return username; }
		public void setUsername(String username) { this.username = username; }
		public String getPassword() { return password; }
		public void setPassword(String password) { this.password = password; }
	}
	
	protected void onLogin(AjaxRequestTarget cible) {
		
	}
	
	private static final class LoginSubmitLink extends AjaxSubmitLink {

		private static final long serialVersionUID = 1L;
		
		public LoginSubmitLink(String id) {
			super(id);
		}

		@Override
		protected void onError(AjaxRequestTarget target, Form<?> form) {
			target.addComponent(form.findParent(LoginPanel.class).get(ID_LOGIN_FORM_FEEDBACK));
		}

		@Override
		protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
			LoginPanel loginPane = form.findParent(LoginPanel.class);
			Credentials credentials = (Credentials) form.getModelObject();
			try {
				loginPane.authBS.login(credentials.getUsername(), credentials.getPassword());
				if (loginPane.callback != null) {
					loginPane.callback.onLogin(target, loginPane.authBS.getUser());
				}
			} catch (InvalidCredentialException e) {
			    if(LOG.isTraceEnabled()) {
			        LOG.trace(e.getMessage(), e);
			    } else {
			        LOG.debug(e.getMessage());
			    }
				getForm().error(loginPane.getString(IMsgs.LOGIN_ERROR));
			} catch (Exception e) {
				LOG.error(e.getMessage(), e);
				getForm().error(loginPane.getString(IMsgs.INTERNAL_ERROR));
			}
		}
	}
}
